home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / tppop18c.arc / POPUP.ASM < prev    next >
Assembly Source File  |  1991-04-28  |  21KB  |  593 lines

  1. LOCALS @@
  2. TITLE   Turbo Pop Version 1.6 beta
  3. SUBTTL  Copyright (c)1988 Ross Neilson Wentworth
  4.  
  5. ; Requires TASM 1.0 to assembler properly.  Minor modifications
  6. ; required to assembler with MASM 5.1.
  7.  
  8. ; This code is Copyright (c)1988 by Ross Neilson Wentworth
  9. ; All Rights Reserved
  10. ;
  11. ; No part of this code may be reproduced, modified, sold, or used
  12. ; as an incentive to buy without the expressed written consent of
  13. ; the author.
  14.  
  15.  
  16. ; Routine Quick Reference
  17. ;
  18. ;   EnterPopUp          Saves and sets the stack then calls a high-
  19. ;                       level routine.
  20. ;   InitializePopUp     Sets the low-level interrupt vectors.
  21. ;   Installed           Sees if the program is already loaded.
  22. ;   new05Int            Optional print-screen trap.
  23. ;   new08int            Called at each timer tick.  Checks to see if we
  24. ;                       want to pop up and whether it is safe to do so.
  25. ;   new09int            Checks for our hotkey combo at each keypress.
  26. ;   new10Int            Optional video BIOS trap.
  27. ;   new13int            Keeps track of when the disk is busy.
  28. ;   new16int            Prevents popups from being locked out while ours
  29. ;                       is active.
  30. ;   new28int            Interrupt routine that is called whenever it is safe
  31. ;                       to interrupt DOS.
  32. ;   new2Fint            Intercepts the Multiplex interupt.
  33.  
  34. TRUE     equ    1
  35. FALSE    equ    0
  36.  
  37. TRAPINT05  EQU  FALSE    ; change to TRUE to trap print-screens
  38. TRAPINT10  EQU  FALSE    ; change to TRUE to trap video BIOS
  39. TRAPINT16  EQU  TRUE     ; prevent others from being locked out
  40.  
  41. .MODEL LARGE
  42.  
  43. DATA   SEGMENT
  44.  
  45. EXTRN prefixseg:WORD
  46.  
  47. DATA   ENDS
  48.  
  49. CODE   SEGMENT
  50.       ASSUME  cs:CODE
  51.  
  52.  
  53. PUBLIC InitializePopUp,Installed
  54.  
  55. EXTRN callpopup:FAR,ReleaseProgram:FAR
  56.  
  57. ;----------------------------------------------------------------------------
  58. ; Miscellaneous data
  59. ;----------------------------------------------------------------------------
  60. hotkey  LABEL  WORD
  61. scancode       DB  0    ; scan code of our hotkey
  62. shiftstatus    DB  0    ; shift key status (alt,ctrl, etc. )
  63.  
  64. program_status DB  0    ; true if the program is active
  65. request_flag   DB  0    ; true if we want to pop-up
  66. notsafe        DB  0    ; non-zero if unsafe to pop up
  67. multiplexID    DB  0    ; unique program ID code
  68.  
  69. stack_pointer  DW  0    ; holds our program's stack pointer
  70. stack_segment  DW  0    ; holds our program's stack segment
  71. old_pointer    DW  0    ; holds the interrupted stack pointer
  72. old_stack      DW  0    ; holds the interrupted stack segment
  73.  
  74. dos_busy_flag  DD  0       ; points to DOS's busy flag
  75.  
  76. ; Follows is the interrupt service routine (ISR) installation table.
  77. ; Each interrupt will have three entries, the interrupt number, the
  78. ; original interrupt vector, and the offset of the ISR.  The entire
  79. ; table is terminated with a zero byte (this disallows the automatic
  80. ; installation of interrupt 00h).  There are two ISR's that are optional.
  81. ; One traps the print-screen interrupt (05h) and the other traps the video
  82. ; BIOS interrupt (10h).  By default, these traps are not used.  If you wish
  83. ; to include them in the interrupt trapping list you must change the EQU's
  84. ; above to TRUE.  TRAPINT05 is the EQU for trapping the print-screen
  85. ; interrupt and TRAPINT10 is the EQU for trapping the video BIOS.
  86.  
  87. ;----------------------------------------------------------------------------
  88. ; Interrupt Vector Table
  89. ;----------------------------------------------------------------------------
  90.  
  91. Vectors  LABEL   BYTE
  92.  
  93. IF TRAPINT05   ; optional interrupt trap
  94.  
  95.                DB  05h     ; print screen vector number
  96. old05int       DD  ?       ; the original print screen interrupt vector
  97.                DW  offset new05int
  98. ENDIF
  99.  
  100.                DB  08h     ; timer tick
  101. old08int       DD  ?       ; the original timer tick interrupt vector
  102.                DW  offset new08int
  103.  
  104.                DB  09h     ; keyboard vector number
  105. old09int       DD  ?       ; the original keyboard interrupt vector
  106.                DW  offset new09int
  107.  
  108. IF TRAPINT10   ; optional interrupt trap
  109.                DB  10h     ; video BIOS vector number
  110. old10int       DD  ?       ; the original video BIOS interrupt vector
  111.                DW  offset new10int
  112. ENDIF
  113.  
  114.                DB  13h     ; disk i/o vector number
  115. old13int       DD  ?       ; the original disk interrupt vector
  116.                DW  offset new13int
  117.  
  118. IF TRAPINT16   ; this trap is not required if you are using Turbo Professional
  119.                DB  16h     ; keyboard vector number
  120. old16int       DD  ?       ; the original keyboard interrupt vector
  121.                DW  offset new16int
  122. ENDIF
  123.  
  124.                DB  28h     ; backprocess vector number
  125. old28int       DD  ?       ; the original backprocess interrupt vector
  126.                DW  offset new28int
  127.  
  128.                DB  2Fh     ; multiplex interrupt number
  129. old2Fint       DD  ?       ; the original multiplex interrupt vector
  130.                DW  offset new2Fint
  131.  
  132.                DB  0       ; end of table
  133.  
  134. ;----------------------------------------------------------------------------
  135. ; Print-Screen Interrupt Service Routine - 05h
  136. ;----------------------------------------------------------------------------
  137. ; This is an optional interrupt trap.  Change the value of TRAPINT05 to
  138. ; TRUE if you want it compiled.  This one traps the PRINT SCREEN interrupt
  139. ; and prevents popping up in the middle of a screen print.
  140.  
  141. IF  trapInt05
  142.  
  143. new05int PROC  FAR
  144.  
  145.          inc       cs:[notsafe]        ; increment status flag
  146.  
  147.          pushf
  148.          cli
  149.          call      cs:[old05int]       ; chain to original INT 05h handler
  150.  
  151.          pushf                         ; preserve flags
  152.          dec       cs:[notsafe]        ; decrement status flag
  153.          popf                          ; restore flags
  154.  
  155.          sti                           ; enable interrupts
  156.          ret       2                   ; return with flags
  157.  
  158. new05int ENDP
  159.  
  160. ENDIF
  161.  
  162. ;----------------------------------------------------------------------------
  163. ; Keyboard Interrupt Service Routine - 09h
  164. ;----------------------------------------------------------------------------
  165. ; Every keystroke is checked through here for our hot_key combination.
  166. ; If our's is pressed, a service request flag is set to TRUE.  If the
  167. ; program is already active we let the keystroke by so that conflicting
  168. ; hot-keys will work.
  169.  
  170. new09int PROC  FAR
  171.  
  172.          sti
  173.          pushf                           ; save the flags
  174.          push      ax                    ; and a register that gets used
  175.          in        al,60h                ; get the keystroke
  176.          cmp       al,cs:[scancode]      ; is it our key?
  177.          jne       @@1                   ; no, so jump to original vector
  178.          mov       ah,2
  179.          int       16h                   ; get the keyboard flags
  180.          and       al,0Fh                ; mask off unused bits
  181.          cmp       al,cs:[shiftstatus]   ; does it match our mask?
  182.          jne       @@1                   ; no, so jump to original vector
  183.          cmp       cs:[program_status],FALSE ; are we already active?
  184.          jne       @@1                   ; yes, so chain to original vector
  185.          cmp       cs:[request_flag],FALSE   ; do we already want serveice?
  186.          je        L200                  ; yes, so chain to original vector
  187. @@1:
  188.          pop       ax                    ; restore used register
  189.          popf                            ; restore flags
  190.          jmp       cs:[old09int]         ; jump to original vector
  191. L200:
  192.          mov       cs:[request_flag],TRUE ; say service is desired
  193.          cli                              ; turn off interrupts
  194.          mov       al,20h                 ; say interrupt is finished
  195.          out       20h,al
  196.          in        al,61h                 ; trash the keystroke
  197.          mov       ah,al
  198.          or        al,80h
  199.          out       61h,al
  200.          jmp       @@2                    ; jump to nowhere for delay
  201. @@2:
  202.          mov       al,ah
  203.          out       61h,al
  204.          pop       ax                     ; restore used register
  205.          popf                             ; restore flags
  206.          iret                             ; all done
  207.  
  208. new09int ENDP
  209.  
  210. ;----------------------------------------------------------------------------
  211. ; Video BIOS Interrupt Service Routine - 10h
  212. ;----------------------------------------------------------------------------
  213. ; This is an optional interrupt trap.  Change the value of TRAPINT10 to
  214. ; TRUE if you want it compiled.  This one traps the video BIOS interrupt
  215. ; and prevents popping up in the middle of any screen activity.
  216.  
  217. IF  trapInt10
  218.  
  219. new10int PROC  FAR
  220.  
  221.          inc       cs:[notsafe]        ; increment status flag
  222.  
  223.          pushf
  224.          cli
  225.          call      cs:[old10int]       ; chain to original INT 10h handler
  226.  
  227.          pushf                         ; preserve flags
  228.          dec       cs:[notsafe]        ; decrement status flag
  229.          popf                          ; restore flags
  230.  
  231.          sti                           ; enable interrupts
  232.          ret       2                   ; return with flags
  233.  
  234. new10int ENDP
  235.  
  236. ENDIF
  237.  
  238. ;----------------------------------------------------------------------------
  239. ; Disk I/O Interrupt Service Routine - 13h
  240. ;----------------------------------------------------------------------------
  241. ; At each disk call, increments an unsafe flag, finishes
  242. ; the disk call, then decrements the unsafe flag.  This
  243. ; prevents an unsafe "popup" during disk i/o.
  244.  
  245. new13int PROC FAR
  246.  
  247.          inc       cs:[notsafe]       ; increment status flag
  248.  
  249.          pushf                         ; chain to original INT 13h handler
  250.          cli
  251.          call      cs:[old13int]
  252.  
  253.          pushf                         ; preserve flags
  254.          dec       cs:[notsafe]        ; decrement status flag
  255.          popf                          ; restore flags
  256.  
  257.          sti                           ; enable interrupts
  258.          ret       2                   ; return with flags, this is to retain
  259.                                        ; any carry flag (error) that may
  260.                                        ; have occurred.
  261.  
  262. new13int ENDP
  263.  
  264. ;----------------------------------------------------------------------------
  265. ; Keyboard interrupt - 16h
  266. ;----------------------------------------------------------------------------
  267. ; Traps the keyboard function to get a key, this is to prevent other resident
  268. ; programs from being locked out while ours is active.
  269.  
  270. IF TrapInt16
  271.  
  272. new16int PROC   FAR
  273.  
  274.          sti
  275.          pushf
  276.          push   ax
  277.          cmp    ah,10h
  278.          je     @@3
  279.          or     ah,ah
  280.          jnz    skip
  281. @@3:
  282.          int    28h              ; backprocess interrupt
  283.          pop    ax
  284.          push   ax
  285.          inc    ah
  286.          pushf
  287.          cli
  288.          call   cs:[old16int]    ; check for a keystroke
  289.          jz     @@3              ; wait for a key
  290.  
  291. skip:
  292.          pop    ax
  293.          popf
  294.          cli
  295.          jmp    cs:[old16int]
  296.  
  297. new16int ENDP
  298.  
  299. ENDIF
  300.  
  301. ;----------------------------------------------------------------------------
  302. ; Timer Tick Interrupt Service Routine - 08h
  303. ;----------------------------------------------------------------------------
  304. ; At each timer tick, this routine sees if our routine wants service.
  305. ; If it does, and it's safe to run, it saves junk and calls our routine.
  306.  
  307. new08int PROC  FAR
  308.  
  309.          pushf
  310.          cli
  311.          call      cs:[old08int]
  312.          cmp       cs:[request_flag],FALSE   ; request flag set?
  313.          je        L400                      ; no, then exit
  314.          push      di
  315.          push      es                        ; save es and di
  316.          les       di,cs:[dos_busy_flag]     ; address of DOS BUSY_FLAG in DI
  317.          cmp       byte ptr es:[di],FALSE    ; DOS service currently active?
  318.          pop       es
  319.          pop       di                        ; clean up the stack
  320.          jne       L400                      ; dos active, so wait
  321.          cmp       cs:[notsafe],FALSE        ; is it safe to pop-up?
  322.          je        EnterPopUp                ; yes, go for it
  323. L400:
  324.          iret                                ; busy or no request
  325.  
  326. new08int ENDP
  327.  
  328. ;----------------------------------------------------------------------------
  329. ; Backprocess Interrupt Service Routine - 28h
  330. ;----------------------------------------------------------------------------
  331. ; Whenever it is safe for a program to interrupt, DOS issues an
  332. ; INT 28h.  This normally occurs while sitting at the command line.
  333. ; This routine checks to see if our program wants service and pops
  334. ; it up if it does.
  335.  
  336. new28int PROC FAR
  337.  
  338.          pushf                             ; call the original interrupt routine
  339.          cli
  340.          call      cs:[old28int]
  341.  
  342.          cmp       cs:[request_flag],FALSE ; do we want to pop up?
  343.          jne       EnterPopUp              ; yes, go pop up
  344.          iret                              ; no. exit
  345.  
  346. new28int ENDP
  347.  
  348. ;----------------------------------------------------------------------------
  349. ; Multiplex Interrupt Service Routine - 2Fh
  350. ;----------------------------------------------------------------------------
  351. ; We use this ISR to check if a program is already loaded as well as to
  352. ; provide special routines needed to unload the program safely.
  353. ;
  354. ; function 0, returns 0FFh in AL to indicate the program is already loaded
  355. ; function 1, returns the vector table in DX:AX
  356. ; function 2, returns the module's code segment (CS) in AX
  357. ; function 3, releases the memory for this program
  358. ;
  359. ; Examine the UNHOOK unit to see how these are used
  360.  
  361. new2Fint PROC  FAR
  362.  
  363.          cmp       ah,cs:[MultiplexID]
  364.          je        @@4
  365.          jmp       cs:[old2Fint]
  366. @@4:
  367.          test      al,al          ; function 0, loaded flag
  368.          jnz       @@5
  369.          mov       al,0FFh
  370.          jmp       short L300
  371. @@5:
  372.          cmp       al,1           ; function 1, return vector table pointer
  373.          jne       @@6
  374.          mov       dx,cs
  375.          lea       ax,cs:[vectors]
  376.          jmp       short L300
  377. @@6:
  378.          cmp       al,2           ; function 2, return code segment
  379.          jne       @@7
  380.          mov       ax,cs
  381.          jmp       short L300
  382. @@7:
  383.          cmp       al,3           ; function 3, release program memory
  384.          jne       @@8
  385.          pushf
  386.          call      ReleaseProgram
  387. @@8:
  388.          cmp       al,4
  389.          jne       L300
  390.          push      es
  391.          mov       ax,DATA
  392.          mov       es,ax
  393.  
  394.          assume    es:DATA
  395.  
  396.          mov       es,es:[prefixseg]
  397.          mov       ax,es:[2]
  398.          inc       ax
  399.  
  400.          pop       es
  401.          assume    es:CODE
  402.  
  403. L300:
  404.          iret
  405.  
  406. new2Fint ENDP
  407.  
  408. ;----------------------------------------------------------------------------
  409. ; Setup For Entering Application
  410. ;----------------------------------------------------------------------------
  411. ; Sets SS, and SP, then calls the popup program.
  412. ; After returning, it restores them.
  413.  
  414. EnterPopUp  PROC   NEAR
  415.  
  416.          mov       cs:[request_flag],FALSE  ; clear the pop up request flag
  417.          mov       cs:[program_status],TRUE ; say program is active
  418.          mov       cs:[old_stack],ss     ; save the stack segment
  419.          mov       cs:[old_pointer],sp   ; save the stack pointer
  420.          cli                             ; turn off interrupts
  421.          mov       ss,cs:[stack_segment] ; get our program's stack segment
  422.          mov       sp,cs:[stack_pointer] ; get our program's stack pointer
  423.          sti                             ; turn interrupts back on
  424.  
  425. ; call the popup procedure indirectly
  426.  
  427.          pushf                           ; simulate an interrupt
  428.          call      CallPopUp
  429.  
  430. ; restore the stack segment and pointer
  431.  
  432.          cli                            ; old cpu bug require ints be off
  433.          mov       ss,cs:[old_stack]
  434.          mov       sp,cs:[old_pointer]
  435.          sti
  436.  
  437.          mov       cs:[program_status],FALSE ; say program is not active
  438.          iret                                ; all done
  439.  
  440. EnterPopUp  ENDP
  441.  
  442. stk_str  STRUC
  443.  
  444. oldbp    DW   ?
  445. return   DW   ?
  446. keycombo DW   ?
  447. multID   DW   ?
  448.  
  449. stk_str  ENDS
  450.  
  451. ;----------------------------------------------------------------------------
  452. ; Initialize memory and the vectors
  453. ;----------------------------------------------------------------------------
  454. ; We save some interrupt vectors and flags in the code segment for
  455. ; efficiency.  We don't want to be pushing and popping all of the
  456. ; registers at every single timer tick and key press.
  457. ;
  458. ; It's too bad there isn't any way of releasing the space used by the
  459. ; initialization code.  This is the reason the most efficient resident
  460. ; programs are written in entirely assembler, complete control of segment
  461. ; ordering.
  462.  
  463. InitializePopUp PROC  NEAR
  464.  
  465. ; save the stack pointer and segment
  466.  
  467.          push      bp
  468.          mov       bp,sp
  469.  
  470. ; save our hot key combo
  471.  
  472.          mov       ax,keycombo[bp]
  473.          mov       cs:[hotkey],ax
  474.  
  475. ; save the TSR's unique ID
  476.  
  477.          mov       ax,multID[bp]
  478.          mov       cs:[multiplexID],al
  479.  
  480. ; save the stack segment and pointer
  481.  
  482.          mov       cs:[stack_segment],ss
  483.          mov       cs:[stack_pointer],sp
  484.  
  485. ; get the DOS busy flag address
  486.  
  487.          mov       ah,34h
  488.          int       21h
  489.          mov       cs:word ptr [dos_busy_flag+2],es
  490.          mov       cs:word ptr [dos_busy_flag],bx
  491.  
  492.          push      ds              ; save the data segment
  493.          push      cs
  494.          pop       ds              ; point to the code segment
  495.  
  496. ; set all of the interrupt vectors
  497.  
  498.          lea       si,vectors
  499.          cld
  500. @@9:
  501.          lodsb                     ; get a vector number
  502.          or        al,al           ; are we done
  503.          jz        @@10            ; yes
  504.          push      ax              ; save the interrupt number
  505.          mov       ah,35h
  506.          int       21h             ; get the old vector
  507.          mov       [si],bx         ; save the offset
  508.          mov       [si+2],es       ; save the segment
  509.          pop       ax              ; get back interrupt number
  510.          mov       ah,25h          ; set the interrupt vector
  511.          mov       dx,[si+4]       ; get the routine offset assume this code segment
  512.          int       21h
  513.          add       si,6            ; point to next item in table
  514.          jmp       short @@9       ; do it again
  515. @@10:
  516.          pop       ds              ; restore the data segment
  517.          pop       bp
  518.          ret       2
  519.  
  520. InitializePopUp  ENDP
  521.  
  522. ;----------------------------------------------------------------------------
  523. ; Checks for a previously installed program
  524. ;----------------------------------------------------------------------------
  525. ; Checks to see if the program is already loaded by using the Multiplex
  526. ; interrupt (2Fh).  It must do some convaluted crap to avoid problems
  527. ; under DOS 2.x.
  528.  
  529. Installed PROC  FAR
  530.  
  531.          push      bp
  532.          mov       bp,sp
  533.          mov       ah,30h
  534.          int       21h            ; get the DOS version
  535.          cmp       al,2
  536.          ja        L101           ; jump if version 3.0 or later
  537.          mov       ax,352Fh       ; get vector for 2Fh
  538.          int       21h
  539.          mov       ax,es
  540.          or        ax,bx          ; jump if current INT 2Fh vector ..
  541.          jnz       L100           ; .. is nonzero
  542.  
  543.          mov       ax,0F000h
  544.          mov       es,ax
  545.          mov       di,-1
  546.          mov       cx,-1
  547.          std
  548.          mov       al,0CFh
  549.          repne     scasb          ; find an IRET in the BIOS
  550.          inc       di
  551.  
  552.          mov       dx,di
  553.          push      ds
  554.          push      es
  555.          pop       ds
  556.          mov       ax,252Fh
  557.          int       21h            ; point 2Fh to an IRET in the BIOS
  558.          pop       ds
  559.          jmp       short L103     ; now go and install it
  560. L100:
  561.          mov       ax,0FF00h      ; look for PRINT.COM
  562.          int       2Fh            ; if resident AH = print queue length
  563.          cmp       ah,0FFh        ; otherwise AH is unchanged
  564.          je        L101           ; use multiplex interrupt
  565.          mov       al,1
  566.          jmp       short L104     ; abort if PRINT.COM already installed
  567. L101:
  568.          mov       ax,[bp+6]      ; get interrupt ID number
  569.          mov       ah,al
  570.          xor       al,al
  571.          int       2Fh            ; poll for the ID number
  572.          test      al,al          ; installed already?
  573.          jz        L103           ; jump if ok to install
  574.          cmp       al,0FFh
  575.          jne       L102           ; jump if not already installed
  576.          mov       al,2
  577.          jmp       short L104     ; error, already installed
  578. L102:
  579.          mov       al,3
  580.          jmp       short L104      ; error, can't install
  581. L103:
  582.          xor       al,al
  583. L104:
  584.          xor       ah,ah
  585.          pop       bp
  586.          ret       2
  587.  
  588. Installed ENDP
  589.  
  590. CODE ENDS
  591.  
  592. END
  593.